package game.engine.base

import java.lang.RuntimeException
import java.lang.StringBuilder
import kotlin.math.cos
import kotlin.math.sin

// 可以用于2d
/**
 *
 * |  a , c , e |
 * |  b , d , f |
 *
 */


class Mat2x3Pool: Pool<Mat2x3>() {
    override fun create(): Mat2x3 {
        return  Mat2x3()
    }
}

class Mat2x3 (
    var a :Float = 1f,
    var b :Float = 0f,
    var c: Float =  0f,
    var d:Float  = 1f,
    var e:Float = 0f,
    var f:Float = 0f
        ){

    companion object{
        val pool = Mat2x3Pool()
    }

    fun identity():Mat2x3{
        a = 1f
        b = 0f
        c = 0f
        d = 1f
        e = 0f
        f = 0f
        return  this
    }

    fun loadTransform(x:Float,y:Float):Mat2x3{
        a = 1f
        b = 0f
        c = 0f
        d = 1f
        e = x
        f = y
        return this
    }

    fun loadRotate(degress:Float):Mat2x3{
        val rad = CoreUtil.toRad(degress)
        val cos = cos(rad)
        val sin = sin(rad)
        a = cos
        b = sin
        c = -sin
        d = cos
        e = 0f
        f = 0f
        return  this
    }

    fun loadScale(sx:Float,sy:Float):Mat2x3{
        a = sx
        b = 0f
        c = 0f
        d = sy
        e = 0f
        f = 0f
        return this
    }

    fun loadTRS(x:Float,y:Float,degress:Float,sx:Float,sy:Float):Mat2x3{
        val rad = CoreUtil.toRad(degress)
        val cos = cos(rad)
        val sin = sin(rad)
        a = cos * sx
        b = sin * sx
        c = -sin * sy
        d = cos * sy
        e = x
        f = y
        return  this
    }

    fun inverse():Mat2x3{
        val a00 = a
        val a01 = b
//        val a02 = 0f

        val a10 = c
        val a11 = d
//        val a12 = 0f

        val a20 = e
        val a21 = f
        val a22 = 1f

        val b01 = a22 * a11
        val b11 = -a22 * a10
        val b21 = a21 * a10 - a11 * a20

        // Calculate the determinant
        var det = a00 * b01 + a01 * b11

        if (det == 0f) {
            throw RuntimeException("矩阵行列式为0,不存在逆矩阵.")
        }
        det = 1.0f / det

        a = b01 * det
        b = (-a22 * a01) * det

        c = b11 * det
        d = (a22 * a00) * det

        e = b21 * det
        f = (-a21 * a00 + a01 * a20) * det

        // needCheckedValue 结果就是1f
//        val needCheckedValue = (a11 * a00 - a01 * a10) * det
        return  this
    }

    fun copyFrom(other:Mat2x3):Mat2x3{
        a = other.a
        b = other.b
        c = other.c
        d = other.d
        e = other.e
        f = other.f
        return this
    }

    fun multiply(rhs:Mat2x3):Mat2x3{
        val n0 = a * rhs.a + c * rhs.b
        val n1 = b * rhs.a + d * rhs.b

        val n3 = a * rhs.c + c * rhs.d
        val n4 = b * rhs.c + d * rhs.d

        val n6 = a * rhs.e + c * rhs.f
        val n7 = b * rhs.e + d * rhs.f

        a = n0
        b = n1
        c = n3
        d = n4
        e = n6
        f = n7
        return this
    }


    // 为了优化
    fun multiplyBy(lhs:Mat2x3,pa:Float,pb:Float,pc:Float,pd:Float,pe:Float,pf:Float){
        a = lhs.a * pa + lhs.c * pb
        b = lhs.b * pa + lhs.d * pb
        c = lhs.a * pc + lhs.c * pd
        d = lhs.b * pc + lhs.d * pd
        e = lhs.a * pe + lhs.c * pf
        f = lhs.b * pe + lhs.d * pf
    }

}

fun Mat2x3.debug_string():String{
    val sb = StringBuilder()
    sb.append("| $a,$c,$e |\n")
    sb.append("| $b,$d,$f |\n")
    return  sb.toString()
}